#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <modbus.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include "msg_queue_peer.h"
#include "shmem.h"

int *num = NULL;             //共享内存的数据量
struct std_node *st = NULL; //共享内存中首个元素地址

union val_t {
    int b_val;   //bool类型存储空间
    int i_val;   //整形值存储空间
    float f_val; //浮点值存储空间
};
struct msg //消息队列的消息类型
{
    long type;       //类型 0：STM32  1：modbus
    int key;         //key 值
    union val_t val; //数据（共用体类型）
};
struct std_node
{
    int key;             //唯一键值
    int type;            //数据点类型
    int dev_type;        //数据点属于哪个设备，根据网关支持的设备自行定义
    union val_t old_val; //变化上报后需要更新旧值
    union val_t new_val; //从共享内存取出最新数据，放到new_val中
    int ret;             //默认为-1，采集成功后设置为0，采集失败再置-1
};
modbus_t *ctx;
// modbus读取设备线程
void *modbus_read(void *arg)
{
    // uint16_t buf[1024] = {};
    uint16_t data[128] = {};
    uint8_t data1[128] = {};
    //初始化创建共享内存
    struct shm_param pa;            //结构体共享内存id'地址，key
    if (shm_init(&pa, "SHMEM", 512)) //共享内存路径
    {
        perror("shm_init err\n");
    }
    num = shm_getaddr(&pa); //num 是一个指向共享内存中整数的指针，用于保存和提供一个 struct std_node 数组的数量。
    if (num == NULL)

    {
        perror("shm getaddr err");
    }
    st = (struct std_node *)(num + 1); //std 指向的内存位置紧随 num 之后，并且这个位置被定为 struct std_node 类型的数组

    while (1) //循环采集数据
    {
        sleep(1);
        modbus_read_registers(ctx, 0, 10, data); //读取寄存器
        modbus_read_bits(ctx, 0, 10, data1);
        uint32_t combined = (data[0] << 16) | data[1]; //combined 组合了两个 16 位寄存器的数据成一个 32 位的值
        uint32_t combined1 = (data[2] << 16) | data[3];
        uint32_t combined2 = (data[4] << 16) | data[5];
        float value;
        float value1;
        float value2;
        memcpy(&value, &combined, sizeof(value)); //使用 memcpy 将这个 32 位的值解释为 float 类型。
        memcpy(&value1, &combined1, sizeof(value1));
        memcpy(&value2, &combined2, sizeof(value2));
        // st->key == 101;
        // shm_write(&pa, st, sizeof(struct std_node));
        printf("num=%d\n", *num);
        printf("%p\n",num);
        printf("%.1f %.1f %.1f\n", value, value1, value2); //数据调试
        printf("%d %d %d \n", data1[0], data1[1], data1[2]);
        for (int i = 0; i < *num; i++)
        {
            if ((st + i)->key == 101) //温度            //判断key
            {
                (st + i)->new_val.f_val = value;
                printf("温度：%.1f\n", (st + i)->new_val.f_val);
            }
            if ((st + i)->key == 102) //湿度
            {
                (st + i)->new_val.f_val = value1;
                printf("湿度：%.1f\n", (st + i)->new_val.f_val);
            }
            if ((st + i)->key == 103) //光照强度
            {
                (st + i)->new_val.f_val = value2;
                printf("光照强度：%.1f\n", (st + i)->new_val.f_val);
            }
            if ((st + i)->key == 104) //空调开关
            {
                (st + i)->new_val.b_val = data1[0];
                printf("空调状态：%d\n", (st + i)->new_val.b_val);
            }
            if ((st + i)->key == 105) //风扇开关
            {
                (st + i)->new_val.i_val = data1[1];
                printf("风扇状态：%d\n", (st + i)->new_val.b_val);
            }
            if ((st + i)->key == 106) //led开关
            {
                (st + i)->new_val.i_val = data1[2];
                printf("led灯状态：%d\n", (st + i)->new_val.b_val);
            }
        }
        memset(data, 0, sizeof(data));
        memset(data1, 0, sizeof(data1));
    }
    shm_del(&pa);
    pthread_exit(NULL);
}
//modbus写入线圈
void *modbus_write(void *arg)
{
    struct msg msg1;
    while (1)
    {
        //用消息队列接收指令
        msg_queue_recv("MSG", &msg1, sizeof(struct msg), 1, 0);
        // printf("msg1.key=%d\n", msg1.key);    //调试
        // printf("msg1.val.b_val=%d\n", msg1.val.b_val);
        if (msg1.key == 104) //空调
        {
            modbus_write_bit(ctx, 0, msg1.val.b_val);
        }
        if (msg1.key == 105) //风扇
        {
            modbus_write_bit(ctx, 1, msg1.val.b_val);
        }
        if (msg1.key == 106) //led
        {
            modbus_write_bit(ctx, 2, msg1.val.b_val);
        }
    }
    pthread_exit(NULL);
}
int main(int argc, char const *argv[])
{
    pthread_t tid, tid1;
    // 1. 创建实例modbus_new_tcp
    ctx = modbus_new_tcp(argv[1], 502);
    if (ctx == NULL)
    {
        perror("modbus create err");
        return -1;
    }
    // 2. 设置从机idmodbus_set_slave
    modbus_set_slave(ctx, 1);
    // 3. 建立连接modbus_connect
    modbus_connect(ctx);
    //4.创建双线程
    if (pthread_create(&tid, NULL, modbus_read, ctx) != 0)
    {
        perror("create error");
        return -1;
    }
    if (pthread_create(&tid1, NULL, modbus_write, ctx) != 0)
    {
        perror("create error");
        return -1;
    }
    pthread_detach(tid);
    pthread_detach(tid1);
    while (1)
        ;
    // 5. 关闭套接字modbus_close
    modbus_close(ctx);
    // 6. 释放实例modbus_free
    modbus_free(ctx);
    return 0;

}